# -*- coding: utf-8 -*-

# 获取引擎服务端API的模块
import mod.server.extraServerApi as serverApi

# 获取引擎服务端System的基类，System都要继承于ServerSystem来调用相关函数
from roseThorn import RoseThorn
from moltenFire import MoltenFire
from nourish import Nourish
from charge import Charging
from iceArmor import IceArmor
from iceFrozen import IceFrozen
from stepWind import StepWind
from betray import Betray
from gemstoneScripts.config.enchantList import *

ServerSystem = serverApi.GetServerSystemCls()

# 附魔效果与实现类的对应表
ENCHANT_EFFECT_MAP = {
    ROSE_THORN: RoseThorn,
    MOLTEN_FIRE: MoltenFire,
    NOURISH: Nourish,
    CHARGING: Charging,
    ICE_FROZEN: IceFrozen,
    STEP_WIND: StepWind,
    ICE_ARMOR: IceArmor,
    BETRAY: Betray
}

# 穿戴生效附魔列表
ARMOR_ENCHANT = [ROSE_THORN, STEP_WIND, ICE_ARMOR]


# 在modMain中注册的Server System类
class EnchantServerSystem(ServerSystem):

    def __init__(self, namespace, systemName):
        super(EnchantServerSystem, self).__init__(namespace, systemName)
        # 玩家已经获得附魔效果
        # self.activeEnchant表结构如下:
        # {playerId1 : {enchantKey1 : enchant1, enchantKey2 : enchant2 }, playerId2 = {enchantKey1 : enchant3, enchantKey2 : enchant4 }, ...}
        self.activeEnchant = {}

        # 开启定时器，每秒对附魔对象进行tick，方便实现循环类型附魔效果
        comp = serverApi.GetEngineCompFactory().CreateGame(serverApi.GetLevelId())
        comp.AddRepeatedTimer(0.05, self.enchant_tick)
        comp.AddRepeatedTimer(1.0, self.enchant_second)

        # 监听事件
        self.ListenEvent()

    def ListenEvent(self):
        # 监听穿着装备变化事件，用于实现穿着类型附魔效果
        self.ListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(),
                            'OnNewArmorExchangeServerEvent', self, self.new_armor_exchange)
        self.ListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(),
                            'OnCarriedNewItemChangedServerEvent', self, self.carried_new_item_change)

    def UnListenEvent(self):
        self.UnListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(),
                              'OnNewArmorExchangeServerEvent', self, self.new_armor_exchange)
        self.UnListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(),
                              'OnCarriedNewItemChangedServerEvent', self, self.carried_new_item_change)

    # 主手武器切换执行操作
    def carried_new_item_change(self, args):
        player_id = args["playerId"]
        old_item_dict = args["oldItemDict"]
        new_item_dict = args["newItemDict"]
        # 移除替换下装备的附魔效果
        self.remove_enchant_effect(player_id, old_item_dict)
        # 添加替换上装备的附魔效果
        self.add_enchant_effect(player_id, new_item_dict)

    # 穿着装备切换执行操作
    def new_armor_exchange(self, args):
        player_id = args["playerId"]
        old_item_dict = args["oldArmorDict"]
        new_item_dict = args["newArmorDict"]

        # 移除切换前装备的附魔效果
        self.remove_enchant_effect(player_id, old_item_dict, True)
        # 添加切换后装备的附魔效果
        self.add_enchant_effect(player_id, new_item_dict, True)

    # 移除附魔效果
    def remove_enchant_effect(self, player_id, old_item_dict, is_armor_change=False):
        # 如果此玩家没有使用过自定义附魔(self.activeEnchant中没有此player的信息)，则直接返回
        if not self.activeEnchant.get(player_id):
            return

        if not old_item_dict:
            return

        # 如果道具为附魔书则不作逻辑处理
        if old_item_dict['newItemName'] == 'minecraft:enchanted_book':
            return

        # 如果自定义附魔类别为空则不作逻辑处理
        mod_enchant_datas = old_item_dict['modEnchantData']
        if len(mod_enchant_datas) <= 0:
            return

        # 遍历玩家身上的附魔效果，如果有则进行移除
        for enchant_data in mod_enchant_datas:
            enchant_identifier = enchant_data[0]
            level = enchant_data[1]
            # 从self.activeEnchant找到匹配玩家，拿到该玩家身上的附魔属性
            player_enchant = self.activeEnchant.get(player_id)
            if enchant_identifier in player_enchant:
                enchant = player_enchant[enchant_identifier]
                if enchant.isArmorEnchant() != is_armor_change:
                    continue
                enchant.levels.remove(level)
                if len(enchant.levels) <= 0:
                    enchant.onExit()
                    del player_enchant[enchant_identifier]

    # 添加附魔效果
    def add_enchant_effect(self, player_id, new_item_dict, is_armor_change=False):
        if not new_item_dict:
            return

        # 如果道具为附魔书则不作逻辑处理
        if new_item_dict["newItemName"] == "minecraft:enchanted_book":
            return

        # 如果自定义附魔类别为空则不作逻辑处理
        mod_enchant_datas = new_item_dict["modEnchantData"]
        if len(mod_enchant_datas) <= 0:
            return

        # 检测self.activeEnchant中是否有相关玩家的附魔属性表，如果没有则创建
        if not self.activeEnchant.get(player_id):
            self.activeEnchant[player_id] = {}

        # 遍历自定义附魔信息，并为玩家添加相应效果
        for enchant_data in mod_enchant_datas:
            enchant_identifier = enchant_data[0]
            enchant_effect_cls = ENCHANT_EFFECT_MAP.get(enchant_identifier)
            level = enchant_data[1]
            if enchant_effect_cls:
                player_enchant = self.activeEnchant[player_id]
                if enchant_identifier in player_enchant:
                    enchant = player_enchant[enchant_identifier]
                    if enchant.isArmorEnchant() != is_armor_change:
                        continue
                    enchant.levels.append(level)
                else:
                    enchant = enchant_effect_cls(self, player_id, enchant_data, [level])
                    # 判断是否是穿戴类型附魔，穿戴类型附魔只能通过OnNewArmorExchangeServerEvent驱动
                    if enchant.isArmorEnchant() != is_armor_change:
                        continue
                    # 执行附魔效果进入函数，添加效果，监听事件等
                    enchant.onEnter()
                    player_enchant[enchant_identifier] = enchant

    def enchant_second(self):
        # 每秒对玩家身上的附魔效果对象进行tick，方便实现循环类型附魔，可看customEnchant2.py
        for _, player_id in enumerate(self.activeEnchant):
            for _, enchant in self.activeEnchant[player_id].iteritems():
                enchant.second()

    def enchant_tick(self):
        # 每秒对玩家身上的附魔效果对象进行tick，方便实现循环类型附魔，可看customEnchant2.py
        for _, player_id in enumerate(self.activeEnchant):
            for _, enchant in self.activeEnchant[player_id].iteritems():
                enchant.tick()
